package com.jboost.modules.app.util;

import com.jboost.common.util.DateUtils;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.JwtBuilder;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.apache.commons.codec.binary.Base64;

import javax.crypto.SecretKey;
import javax.crypto.spec.SecretKeySpec;
import java.io.UnsupportedEncodingException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

public class JwtUtil {
    /**
     * token 过期时间, 单位: 秒. 这个值表示 2000 天
     */

    private static final long TOKEN_EXPIRED_TIME = 2000 * 24 * 60 * 60;


    /**
     * jwt 加密解密密钥, 这里请自行赋值，本人暂且使用随机数16位
     */
    private static final String JWT_SECRET = "5tgXUOntBfD8xblt70XBgF4p";


    public static final String jwtId = "tokenId";
    /**
     * 创建JWT
     * @param claims 这个是payLoad的部分内容, jwt格式：jwtHeader.jwtPayLoad.Signature
     */
    public static String createJWT(Map<String, Object> claims,String screct) throws UnsupportedEncodingException {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; //指定签名的时候使用的签名算法，也就是header那部分，jjwt已经将这部分内容封装好了。
        long nowMillis = System.currentTimeMillis();//生成JWT的时间
        //下面就是在为payload添加各种标准声明和私有声明了
        Map<String,Object> tokenMap = new HashMap<>();
        tokenMap.put("alg","HS256");
        tokenMap.put("type","JWT");
        JwtBuilder builder = Jwts.builder() //这里其实就是new一个JwtBuilder，设置jwt的body
                .setClaims(claims)         //如果有私有声明，一定要先设置这个自己创建的私有的声明，这个是给builder的claim赋值，一旦写在标准的声明赋值之后，就是覆盖了那些标准的声明的
                //.setId(jwtId)                  //设置jti(JWT ID)：是JWT的唯一标识，根据业务需要，这个可以设置为一个不重复的值，主要用来作为一次性token,从而回避重放攻击。
                //.setIssuedAt(now)           //iat: jwt的签发时间
                .setHeader(tokenMap)
                .setIssuedAt(new Date())//设置header
                .signWith(signatureAlgorithm, generalKey(screct)).setExpiration(DateUtils.addDays(new Date(),2));//设置签名使用的签名算法和签名使用的秘钥
        return builder.compact();
    }


    /**
     * 验证jwt
     */
    public static Claims verifyJwt(String token) {
        //签名秘钥，和生成的签名的秘钥一模一样
        Claims claims;
        try {
            claims = Jwts.parser()  //得到DefaultJwtParser
                    .setSigningKey(generalKey(token))         //设置签名的秘钥
                    .parseClaimsJws(token).getBody();
        } catch (Exception e) {
            claims = null;
        }//设置需要解析的jwt
        return claims;

    }


    public static void main(String[] args) {
        String token = "eyJ0eXBlIjoiSldUIiwiYWxnIjoiSFMyNTYifQ.eyJ0eXBlIjoic3NvX3JlcyIsInVzZXJuYW1lIjoiRWF2YW4iLCJpc3MiOiJodHRwczovL2ZpMzAyMTA4ODguemljcC5mdW4iLCJhdWQiOiJjb20uamlhbmRhb3l1biIsImlhdCI6MTY3NDMwMTk2NiwiZXhwIjoxNjc0NDc0NzY2fQ.Nq75y0fC77h8EFN4KAEu7bfh_N3KSOTWK6NC81tsaII";
        Claims claims = verifyJwt(token);
    }

    /**
     * 由字符串生成加密key
     *
     * @return
     */
    public static SecretKey generalKey(String stringKey) throws UnsupportedEncodingException {
        byte[] encodedKey = stringKey.getBytes("utf-8");
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "HS256");
        return key;

    }

}
